﻿/*!
 * Copyright (c), 上海沃恩信息科技有限公司.
 * All rights reserved.
 * Licensed under BSD (https://www.pittypat.work/bsd.html).
 */

namespace Pittypat
{
    /// <summary>
    /// 提供对标识符字符串的扩展方法。
    /// </summary>
    public static class IdentifierHelper
    {
        // 检查指定的字符是否是一个字母。
        static bool IsLetter(this char c)
        {
            return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
        }

        // 检查指定的字符是否是一个数字。
        static bool IsDigit(this char c)
        {
            return c >= '0' && c <= '9';
        }

        /// <summary>
        /// 检查指定的字符串是否是一个有效的标识符。
        /// </summary>
        /// <param name="s">要检查的字符串。</param>
        /// <returns>s 的长度大于 0，小于或等于 30，第一个字符必须是字母或下划线，其他字符可以是数字、字母或下划线。</returns>
        public static bool IsIdentifier(this string s)
        {
            if (string.IsNullOrEmpty(s))
            {
                return false;
            }

            // 长度不能超过 30
            if (s.Length > 30)
            {
                return false;
            }

            // 首字符必须是字母或下划线
            if (!s[0].IsLetter() && s[0] != '_')
            {
                return false;
            }

            // 其他字符必须是字母、下划线或数字
            for (int i = 1; i < s.Length; ++i)
            {
                if (!s[0].IsLetter() && !s[0].IsDigit() && s[0] != '_')
                {
                    return false;
                }
            }

            return true;
        }

        /// <summary>
        /// 将指定的标识符转换为 Pascal 格式。
        /// </summary>
        /// <param name="t">标识符字符串。</param>
        /// <returns>Pascal 格式的标识符。</returns>
        public static string Pascal(this string t)
        {
            if (string.IsNullOrEmpty(t))
            {
                return "";
            }

            // 如果第一个字符是下划线或大写字母，则原样返回
            if (t[0] == '_' || (t[0] >= 'A' && t[0] <= 'Z'))
            {
                return t;
            }

            // 如果长度为 1，返回大写形式
            if (t.Length <= 1)
            {
                return t.ToUpper();
            }

            return t.Substring(0, 1).ToUpper() + t.Substring(1);
        }

        /// <summary>
        /// 将指定的标识符转换为 camel 格式。
        /// </summary>
        /// <param name="t">标识符字符串。</param>
        /// <returns>camel 格式的标识符。</returns>
        public static string Camel(this string t)
        {
            if (string.IsNullOrEmpty(t))
            {
                return "";
            }
            
            // 如果第一个字符是下划线或小写字母，则原样返回
            if (t[0] == '_' || (t[0] >= 'a' && t[0] <= 'z'))
            {
                return t;
            }

            // 如果长度为 1，返回小写形式
            if (t.Length <= 1)
            {
                return t.ToLower();
            }

            // 如果所有的字符都是大写，则直接将所有的字符转换为小写
            bool all = true;
            foreach (var c in t)
            {
                if (!(c >= 'A' && c <= 'Z') && c != '_' && !(c >= '0' && c <= '9'))
                {
                    all = false;
                    break;
                }
            }

            if (all)
            {
                // 没有任何字符是小写形式，要么是大写，要么是下划线，要么是数字
                return t.ToLower();
            }

            // 将首字符转换为小写
            return t.Substring(0, 1).ToLower() + t.Substring(1);
        }
    }
}
